﻿using MyK3CloudCore.IOC.Attributes;
using MyK3CloudCore.IOC.Cache;
using MyK3CloudCore.IOC.DataEntity;
using MyK3CloudCore.IOC.DataEntity.PresetEntity;
using MyK3CloudCore.IOC.Extensions;
using Newtonsoft.Json;
using SQLBuilder.Enums;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using K3Ioc = Microsoft.Extensions.DependencyInjection.K3IOCServiceCollectionExtensions;

namespace MyK3CloudCore.IOC.K3Client;

public partial class K3CloudApiClient
{
    private readonly K3Config k3Config;
    public K3CloudApiClient(K3Config config)
    {
        k3Config = config;
    }

    /// <summary>
    /// 切换用户
    /// </summary>
    public K3CloudApiClient User(string userName, string? password = null)
    {
        if (string.IsNullOrEmpty(userName)) return this;
        k3Config.UserName = userName;
        k3Config.Password = password;
        return this;
    }

    /// <summary>
    /// 用户验证
    /// 用在需要频繁切换用户时(如AWMS)请将缓存部分代码注释掉
    /// </summary>
    public async Task<bool> ValidateUserAsync(CancellationToken cancellation = default)
    {
        if (!string.IsNullOrEmpty(k3Config.Password)) { return await ValidateUserAsync(k3Config.UserName, k3Config.Password, cancellation); }
        var cache = MemoryCacheHelper<bool>.GetInstance();
        var cacheKey = string.Join("_", k3Config.AcctId, k3Config.AppID, k3Config.AppSecret, k3Config.UserName);
        if (cache.ContainsKey(cacheKey)) { return cache.Get(cacheKey); }
        object[] Parameters = { k3Config.AcctId, k3Config.UserName, k3Config.AppID, k3Config.AppSecret, k3Config.LCID };
        var httpClient = new K3CloudHttpClient
        {
            BaseUrl = k3Config.ServerHost,
            Path = "/Kingdee.BOS.WebApi.ServicesStub.AuthService.LoginByAppSecret.common.kdsvc",
            Content = JsonConvert.SerializeObject(Parameters)
        };
        var htmlContent = await httpClient.PostAsync(cancellation);
        var result = JsonConvert.DeserializeObject<LoginResult>(htmlContent);
        K3Ioc.LoginResult = result;
        cache.Add(cacheKey, result?.LoginResultType == LoginResultType.Success, k3Config.ConnectionValidTime * 60);
        return result?.LoginResultType == LoginResultType.Success;
    }

    public async Task<bool> ValidateUserAsync(string user, string pass, CancellationToken cancellation = default)
    {
        var Parameters = new object[4] { k3Config.AcctId, user, pass, k3Config.LCID };
        var httpClient = new K3CloudHttpClient
        {
            BaseUrl = k3Config.ServerHost,
            Path = "/Kingdee.BOS.WebApi.ServicesStub.AuthService.ValidateUser.common.kdsvc",
            Content = JsonConvert.SerializeObject(Parameters)
        };
        var htmlContent = await httpClient.PostAsync(cancellation);
        var result = JsonConvert.DeserializeObject<LoginResult>(htmlContent);
        K3Ioc.LoginResult = result;
        return result?.LoginResultType == LoginResultType.Success;
    }

    #region 表单查询
    /// <summary>
    /// 查询表单
    /// </summary>
    /// <typeparam name="T">表单class</typeparam>
    /// <param name="field">字段(多字段用,隔开)</param>
    /// <param name="filter">筛选表达式</param>
    /// <param name="order">排序规则(asc或desc)</param>
    /// <param name="topRowCount">返回总行数，整型（非必录）</param>
    /// <param name="startRow">开始行索引，整型（非必录）</param>
    /// <param name="limit">最大行数，整型，不能超过2000（非必录）</param>
    /// <returns></returns>
    public async Task<List<T>> NativeExecuteBillQueryAsync<T>(string? field = null, string filter = "", string order = "", int topRowCount = 0, int startRow = 0, int limit = 0)
    {
        var formId = typeof(T).GetAlias();
        List<T> list = new();
        PropertyInfo[] fieldProperties = typeof(T).GetProperties().Where(t => t.GetCustomAttributes(typeof(ignoreAttribute), true).Length == 0).ToArray();
        if (field != null)
        {
            var fields = field.Split(",");
            PropertyInfo[] p = new PropertyInfo[fields.Length];
            for (int i = 0; i < fields.Length; i++)
            {   //有别名则找到别名属性
                p[i] = fieldProperties.Where(t => t.GetCustomAttribute<AliasAttribute>() == null ? t.Name.Equals(fields[i], StringComparison.OrdinalIgnoreCase) : t.GetCustomAttribute<AliasAttribute>().Name.Equals(fields[i], StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
                if (p[i] == null)
                {   //约定__(双下划线互换)
                    p[i] = fieldProperties.Where(t => t.Name.Equals(fields[i].Replace(".", "__"), StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
                }
            }
            fieldProperties = p;
        }
        else
        {   //约定__(双下划线互换)
            field = string.Join(",", fieldProperties.Select(x => x.GetCustomAttribute<AliasAttribute>()?.Name ?? x.Name).ToArray()).Replace("__", ".");
        }
        var rest = await NativeExecuteBillQueryAsync(formId, field, filter, order, topRowCount, startRow, limit);
        if (rest == null) { return list; }
        List<List<object>>? data = JsonConvert.DeserializeObject<List<List<object>>>(rest);
        if (data == null) { return list; }
        if (data.Count == 0) { return list; }
        for (int i = 0; i < data.Count; i++)
        {
            var item = Activator.CreateInstance<T>();
            if (item == null) continue;
            for (int j = 0; j < fieldProperties.Length; j++)
            {
                if (data[i][j] == null) { continue; }
                object? propertyValue = ConvertNullableType(data[i][j], item.GetType().GetProperty(fieldProperties[j].Name).PropertyType);
                SetPropertyValue(item, fieldProperties[j].Name, propertyValue);
            }
            list.Add(item);
        }
        return list;
    }
    /// <summary>
    /// 查询表单
    /// </summary>
    /// <param name="formId">表单Id</param>
    /// <param name="field">字段(多字段用,隔开)</param>
    /// <param name="filter">筛选表达式</param>
    /// <param name="order">排序规则(asc或desc)</param>
    /// <param name="topRowCount">返回总行数，整型（非必录）</param>
    /// <param name="startRow">开始行索引，整型（非必录）</param>
    /// <param name="limit">最大行数，整型，不能超过2000（非必录）</param>
    public async Task<string?> NativeExecuteBillQueryAsync(string formId, string field, string filter = "", string order = "", int topRowCount = 0, int startRow = 0, int limit = 0)
    {
        var obj = new
        {
            FormId = formId,
            FieldKeys = field,
            FilterString = filter,
            OrderString = order,
            TopRowCount = topRowCount,
            StartRow = startRow,
            Limit = limit
        };
        var rest = await ExecuteAsync("Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.ExecuteBillQuery", obj);
        if (rest == null) return null;
        if (rest == "[]") { return null; }
        if (rest.Contains("MsgCode") || rest.Contains("_Bracket")) { throw new Exception(rest); }
        return rest;
    }

    /// <summary>
    /// 表单查询(json)
    /// </summary>
    /// <param name="field"> 字段可以使用别名 如：FMaterialId.FNumber AS FNumber </param>
    public async Task<string?> NativeBillQueryAsync(string formId, string field, string filter = "", string order = "", int topRowCount = 0, int startRow = 0, int limit = 0)
    {
        var obj = new
        {
            FormId = formId,
            FieldKeys = field,
            FilterString = filter,
            OrderString = order,
            TopRowCount = topRowCount,
            StartRow = startRow,
            Limit = limit
        };
        var rest = await ExecuteAsync("Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.BillQuery", obj);
        if (rest == null) return null;
        if (rest == "[]") { return null; }
        if (rest.Contains("MsgCode") || rest.Contains("_Bracket")) { throw new Exception(rest); }
        return rest;
    }
    /// <summary>
    /// 原生态表单查询
    /// </summary>
    public async Task<string?> NativeExecuteBillQueryAsync(string formId, string field, K3FilterString[] filter, string order = "", int topRowCount = 0, int startRow = 0, int limit = 0)
    {
        var obj = new
        {
            FormId = formId,
            FieldKeys = field,
            FilterString = filter,
            OrderString = order,
            TopRowCount = topRowCount,
            StartRow = startRow,
            Limit = limit
        };
        var rest = await ExecuteAsync("Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.ExecuteBillQuery", obj);
        if (rest == null) return null;
        if (rest == "[]") { return null; }
        if (rest.Contains("MsgCode") || rest.Contains("_Bracket")) { throw new Exception(rest); }
        return rest;
    }
    /// <summary>
    /// 查询表单
    /// </summary>
    public async Task<List<T>> ExecuteBillQueryAsync<T>(string? filterString = null, string? orderString = null, int topRowCount = 0, int startRow = 0, int limit = 0) where T : class
    {
        return await NativeExecuteBillQueryAsync<T>(null, filterString ?? "", orderString ?? "", topRowCount, startRow, limit);
    }

    /// <summary>
    /// 查询表单
    /// </summary>
    public async Task<List<T>> ExecuteBillQueryAsync<T>(Expression<Func<T, bool>> filterExpression, string? orderString = null, int topRowCount = 0, int startRow = 0, int limit = 0) where T : class
    {
        var filterString = ExpressionBuilder.GetFilterString(filterExpression);
        return await ExecuteBillQueryAsync<T>(filterString, orderString, topRowCount, startRow, limit);
    }

    /// <summary>
    /// 查询表单
    /// </summary>
    public async Task<List<T>> ExecuteBillQueryAsync<T>(Expression<Func<T, bool>>? filterExpression, Expression<Func<T, object>>? orderExpression, OrderType[]? orders = default, int topRowCount = 0, int startRow = 0, int limit = 0) where T : class
    {
        var filterString = ExpressionBuilder.GetFilterString(filterExpression);
        var orderString = ExpressionBuilder.GetOrderString(orderExpression, orders);
        return await ExecuteBillQueryAsync<T>(filterString, orderString, topRowCount, startRow, limit);
    }

    /// <summary>
    /// 查询表单<typeparamref name="T"/> 的链式操作
    /// </summary>
    /// <typeparam name="T">表单类</typeparam>
    public IK3Queryable<T> Queryable<T>() where T : class
    {
        return new K3Queryable<T>();
    }
    /// <summary>
    /// 查询表单<typeparamref name="T"/> 的链式操作
    /// </summary>
    public IK3Queryable<T> Queryable<T>(Expression<Func<T, bool>>? whereExpression) where T : class
    {
        return new K3Queryable<T>(whereExpression);
    }
    /// <summary>
    /// WebAPI查询记录总数
    /// </summary>
    /// <param name="countField">计数字段（有分录明细时不要设置成单据头字段）</param>
    public async Task<int> GetTotalCountAsync<T>(Expression<Func<T, bool>>? filterExpression, string countField) where T : class
    {
        if (filterExpression == null) return 0;
        if (string.IsNullOrWhiteSpace(countField)) return 0;
        PropertyInfo property = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(x => x.Name.Equals(countField, StringComparison.OrdinalIgnoreCase)).FirstOrDefault() ?? throw new ArgumentException($"不存在{countField}属性,请检查!");
        if (property.PropertyType == typeof(int) ||
            property.PropertyType == typeof(int?) ||
            property.PropertyType == typeof(float) ||
            property.PropertyType == typeof(float?) ||
            property.PropertyType == typeof(double) ||
            property.PropertyType == typeof(double?) ||
            property.PropertyType == typeof(decimal) ||
            property.PropertyType == typeof(decimal?))
        {
            filterExpression = filterExpression.AddFilter(countField, "<>", 0);
        }
        else
        {
            filterExpression = filterExpression.AddFilter(countField, "<>", null);
        }
        string filter = ExpressionBuilder.GetFilterString(filterExpression);
        var formId = typeof(T).GetAlias();
        var rest = await NativeExecuteBillQueryAsync(formId, "count(1) AS BillCount", filter);
        if (rest == null) return 0;
        List<List<object>>? res = JsonConvert.DeserializeObject<List<List<object>>?>(rest);
        return res == null ? 0 : int.Parse(res[0][0].ToString());
    }

    /// <summary>
    /// WebAPI查询记录 合计
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="filterExpression">筛选条件</param>
    /// <param name="sumFiled">合计字段</param>
    /// <returns></returns>
    public async Task<Dictionary<string, decimal>?> GetSumAsync<T>(Expression<Func<T, bool>>? filterExpression, params string[] sumFiled) where T : class
    {
        if (sumFiled.Length == 0) { return null; }
        Dictionary<string, decimal> dic = new();
        List<string> fildStr = new();
        Expression<Func<T, bool>> tmp = default;
        foreach (var item in sumFiled)
        {
            tmp = tmp.AddFilter(item, "<>", 0, EnumAndOr.Or);
            fildStr.Add($"sum({item}) AS {item}");
        }
        var msql = ExpressionBuilder.GetFilterString(tmp);
        var ksql = ExpressionBuilder.GetFilterString(filterExpression);
        string filter = string.IsNullOrEmpty(ksql) ? msql : ksql + $" AND ({msql})";
        var rest = await NativeExecuteBillQueryAsync(typeof(T).GetAlias(), string.Join(",", fildStr), filter);
        if (rest == null) return dic;
        rest = rest.Replace("null", "0");
        var data = JsonConvert.DeserializeObject<List<List<decimal>>>(rest);
        for (int i = 0; i < sumFiled.Length; i++)
        {
            if (data == null)
            {
                dic.Add(sumFiled[i], 0);
            }
            else
            {
                dic.Add(sumFiled[i], data[0][i]);
            }
        }
        return dic;
    }

    /// <summary>
    /// 即时库存查询
    /// </summary>
    /// <returns></returns>
    public async Task<ResponseModel?> GetInventoryDataAsync(InventoryParamModel paramData)
    {
        var rest = await ExecuteAsync("Kingdee.K3.SCM.WebApi.ServicesStub.InventoryQueryService.GetInventoryData", JsonConvert.SerializeObject(new[] { paramData }), true);
        if (rest == null) return null;
        return JsonConvert.DeserializeObject<ResponseModel>(rest);
    }
    #endregion

    #region 表单保存
    /// <summary>
    /// 表单保存
    /// </summary>
    /// <param name="bill">表单</param>
    /// <param name="IsAutoSubmitAndAudit">自动提交审核</param>
    /// <returns></returns>
    public async Task<K3ApiResult<K3SaveResult>?> SaveAsync<T>(K3SaveParam<T> bill, bool IsAutoSubmitAndAudit = false) where T : class
    {
        var FormId = bill.GetFormId();
        var response = await SaveAsync(FormId, bill);
        if (response == null) return null;
        var saveResult = JsonConvert.DeserializeObject<K3ApiResult<K3SaveResult>?>(response);
        if (saveResult == null) return null;
        if (IsAutoSubmitAndAudit)
        {
            if (saveResult.Result.ResponseStatus.IsSuccess)
            {
                var pkId = saveResult.Result.ResponseStatus.SuccessEntitys[0].Id;
                var submitResult = await SubmitAsync(FormId, pkId);
                if (submitResult == null) return null;
                if (submitResult.Result.ResponseStatus.IsSuccess)
                {
                    var auditResult = await AuditAsync(FormId, pkId);
                    return auditResult;
                }
                return submitResult;
            }
        }
        return saveResult;
    }
    public async Task<string?> SaveAsync(string formid, object obj)
    {
        return await ExecuteAsync("Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Save", formid, obj);
    }
    /// <summary>
    /// 表单保存(复杂的更新操作,需要手工拼接json时使用)
    /// </summary>
    public async Task<string?> SaveAsync(string content)
    {
        return await ExecuteAsync("Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Save", content);
    }
    #endregion
    /// <summary>
    /// 表单提交
    /// </summary>
    /// <param name="FormId"></param>
    /// <param name="FId"></param>
    /// <returns></returns>
    public async Task<K3ApiResult<K3SaveResult>?> SubmitAsync(string FormId, object FId)
    {
        var bill = new
        {
            CreateOrgId = 0,
            Numbers = Array.Empty<string>(),
            Ids = $"{FId}",
            SelectedPostId = 0,
            NetworkCtrl = "",
            IgnoreInterationFlag = ""
        };
        var rest = await ExecuteAsync("Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Submit", FormId, bill);
        return rest == null ? null : JsonConvert.DeserializeObject<K3ApiResult<K3SaveResult>>(rest);
    }

    /// <summary>
    /// 表单审核
    /// </summary>
    /// <param name="FormId"></param>
    /// <param name="FId"></param>
    /// <returns></returns>
    public async Task<K3ApiResult<K3SaveResult>?> AuditAsync(string FormId, object FId)
    {
        var bill = new
        {
            CreateOrgId = 0,
            Numbers = Array.Empty<string>(),
            Ids = $"{FId}",
            InterationFlags = "",
            NetworkCtrl = "",
            IsVerifyProcInst = "",
            IgnoreInterationFlag = ""
        };
        var rest = await ExecuteAsync("Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Audit", FormId, bill);
        if (rest == null) return null;
        return JsonConvert.DeserializeObject<K3ApiResult<K3SaveResult>?>(rest);
    }

    /// <summary>
    /// 撤销服务接口
    /// </summary>
    /// <returns></returns>
    public async Task<K3ApiResult<K3SaveResult>?> CancelAssign(string FormId, int FId)
    {
        var bill = new
        {
            CreateOrgId = 0,
            Numbers = Array.Empty<string>(),
            Ids = $"{FId}",
            NetworkCtrl = ""
        };
        var rest = await ExecuteAsync("Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.CancelAssign", FormId, bill);
        if (rest == null) return null;
        return JsonConvert.DeserializeObject<K3ApiResult<K3SaveResult>?>(rest);

    }

    /// <summary>
    /// 表单撤销提交或者反审核
    /// </summary>
    /// <param name="FormId"></param>
    /// <param name="FId"></param>
    /// <returns></returns>
    public async Task<K3ApiResult<K3SaveResult>?> UnAuditAsync(string FormId, int FId)
    {
        var bill = new
        {
            CreateOrgId = 0,
            Numbers = Array.Empty<string>(),
            Ids = $"{FId}",
            InterationFlags = "",
            NetworkCtrl = "",
            IsVerifyProcInst = ""
        };
        var rest = await ExecuteAsync("Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.UnAudit", FormId, bill);
        if (rest == null) return null;
        return JsonConvert.DeserializeObject<K3ApiResult<K3SaveResult>?>(rest);

    }

    /// <summary>
    /// 表单删除
    /// </summary>
    /// <param name="FormId"></param>
    /// <param name="FId"></param>
    /// <returns></returns>
    public async Task<K3ApiResult<K3SaveResult>?> DeleteAsync(string FormId, int FId)
    {
        var bill = new
        {
            CreateOrgId = 0,
            Numbers = Array.Empty<string>(),
            Ids = $"{FId}",
            NetworkCtrl = ""
        };
        var rest = await ExecuteAsync("Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Delete", FormId, bill);
        return rest == null ? null : JsonConvert.DeserializeObject<K3ApiResult<K3SaveResult>>(rest);
    }

    /// <summary>
    /// 下推单据
    /// </summary>
    /// <param name="FormId">表单ID</param>
    /// <param name="entryIds">分录内码,多条分录用逗号分隔</param>
    /// <param name="ruleId">单据转换内码</param>
    /// <param name="user"></param>
    /// <param name="pass"></param>
    /// <returns></returns>
    public async Task<K3ApiResult<K3SaveResult>?> PushAsync(string FormId, string entryIds, string ruleId)
    {
        var data = new
        {
            Ids = "",
            Numbers = Array.Empty<string>(),
            EntryIds = entryIds,
            RuleId = ruleId,
            TargetBillTypeId = "",
            TargetOrgId = 0,
            TargetFormId = "",
            IsEnableDefaultRule = "false",
            IsDraftWhenSaveFail = "false",
            CustomParams = new { }
        };
        var rest = await ExecuteAsync("Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Push", FormId, data);
        if (rest == null) return null;
        return JsonConvert.DeserializeObject<K3ApiResult<K3SaveResult>?>(rest);
    }

    /// <summary>
    /// 操作接口
    /// </summary>
    /// <returns></returns>
    public async Task<K3ApiResult<K3SaveResult>?> ExcuteOperationAsync(string formid, string opNumber, object data)
    {
        var obj = new object[3] { formid, opNumber, data };
        var rest = await ExecuteAsync("Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.ExcuteOperation", JsonConvert.SerializeObject(obj));
        if (rest == null) return null;
        return JsonConvert.DeserializeObject<K3ApiResult<K3SaveResult>?>(rest);
    }
    #region 生产订单操作接口
    /// <summary>
    /// 生产订单强制结案
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns>
    public async Task<K3ApiResult<K3SaveResult>?> ForceCloseAsync(ExcuteOperationData data)
    {
        return await ExcuteOperationAsync("PRD_MO", "ForceClose", data);
    }
    /// <summary>
    /// 生产订单反执行至完工
    /// </summary>
    public async Task<K3ApiResult<K3SaveResult>?> UndoToFinishAsync(ExcuteOperationData data)
    {
        return await ExcuteOperationAsync("PRD_MO", "UndoToFinish", data);
    }
    #endregion
    public async Task<K3ApiResult<K3SaveResult>?> SendMessage(Expression<Func<SEC_User, bool>> expression, string title, string content, string? FormId = null, string? FId = null)
    {
        var user = await ExecuteBillQueryAsync(expression);
        var userIds = string.Join(",", user.Select(t => t.FUserId).ToArray());
        List<K3MessageModel> msgList = new()
        {
            new K3MessageModel
            {
                FTitle = title,
                FContent = content,
                FReceivers = userIds,
                FObjectTypeId = FormId,
                FKeyValue = FId
            }
        };
        var rest = await SendMessage(msgList);
        return rest;
    }

    public async Task<K3ApiResult<K3SaveResult>?> SendMessage(List<K3MessageModel> models)
    {
        var data = new K3CloudMessage(models);
        var rest = await ExecuteAsync("Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.SendMsg", data);
        if (rest == null) return null;
        return JsonConvert.DeserializeObject<K3ApiResult<K3SaveResult>?>(rest);
    }

    /// <summary>
    /// 元数据查询
    /// </summary>
    /// <param name="FormId">业务对象表单Id（必录）</param>
    /// <returns></returns>
    public async Task<K3ApiResult<K3BusinessInfoResult>?> QueryBusinessInfoAsync(string FormId)
    {
        if (string.IsNullOrEmpty(FormId)) return null;
        var rest = await ExecuteAsync("Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.QueryBusinessInfo", new { FormId });
        if (rest == null) return null;
        return JsonConvert.DeserializeObject<K3ApiResult<K3BusinessInfoResult>>(rest);
    }

    /// <summary>
    /// 元数据查询
    /// </summary>
    public async Task<K3ApiResult<K3BusinessInfoResult>?> QueryBusinessInfoAsync<T>()
    {
        var FormId = typeof(T).GetAlias();
        return await QueryBusinessInfoAsync(FormId);
    }
    public async Task<List<DataCenter>?> GetDataCentersAsync()
    {
        var httpContent = new K3CloudHttpClient
        {
            BaseUrl = k3Config.ServerHost,
            Path = "/Kingdee.BOS.ServiceFacade.ServicesStub.Account.AccountService.GetDataCenterList.common.kdsvc"
        };
        return JsonConvert.DeserializeObject<List<DataCenter>?>(await httpContent.GetAsync());
    }

    /// <summary>
    /// 请求自定义接口
    /// 如：获取汇率体系元数据
    /// var pram =  new { FormId = "BD_Rate" };
    /// var ret = await K3Scoped.Client.QueryCustomAsync("Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.QueryBusinessInfo", pram);
    /// </summary>
    /// <param name="servicename">服务名</param>
    /// <param name="data">参数</param>
    /// <returns></returns>
    public async Task<string?> ExecuteAsync(string servicename, object? data)
    {
        return await ExecuteAsync(servicename, data == null ? null : JsonConvert.SerializeObject(new object[1] { data }));
    }
    public async Task<string?> ExecuteAsync(string servicename, string formid, object? data)
    {
        return await ExecuteAsync(servicename, JsonConvert.SerializeObject(new object[2] { formid, data ?? "" }));
    }

    public async Task<string?> ExecuteAsync(string servicename, string? parameters)
    {
        bool validate;
        if (k3Config.UserName != null && k3Config.Password != null)
        {
            validate = await ValidateUserAsync(k3Config.UserName, k3Config.Password);
        }
        else
        {
            validate = await ValidateUserAsync();
        }
        if (validate)
        {
            K3CloudHttpClient client = new()
            {
                BaseUrl = k3Config.ServerHost,
                Path = $"/{servicename}.common.kdsvc",
                Content = parameters
            };
            return await client.PostAsync();
        }
        return null;
    }
    /// <summary>
    /// 下载文件服务器附件
    /// </summary>
    public async Task<string?> Download(string _fileId)
    {
        var data = new
        {
            FileId = _fileId,
            StartIndex = 0
        };
        return await ExecuteAsync("Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.AttachmentDownLoad", data);
    }

    /// <summary>
    /// 附件上传
    /// </summary>
    public async Task<string?> UploadToBill(string FileName, string FormId, bool IsLast, string InterId, string BillNO, string SendByte, string? AliasFileName)
    {
        var data = new
        {
            FileName,
            FormId,
            IsLast,
            InterId,
            BillNO,
            AliasFileName,
            SendByte
        };
        return await ExecuteAsync("Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.AttachmentUpLoad", data);
    }

    /// <summary>
    /// 转换可空类型值
    /// </summary>
    /// <returns></returns>
    [DebuggerStepThrough]
    private static object? ConvertNullableType(object value, Type conversionType)
    {
        if (conversionType.IsGenericType && conversionType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
        {
            if (value != null)
            {
                NullableConverter nullableConverter = new(conversionType);
                conversionType = nullableConverter.UnderlyingType;
            }
            else
            {
                return null;
            }
        }
        try
        {
            return Convert.ChangeType(value, conversionType);
        }
        catch
        {
            return Activator.CreateInstance(conversionType);
        }
    }

    /// <summary>
    /// 给属性赋值
    /// </summary>
    /// <param name="objectValue">this</param>
    /// <param name="propertyName">属性名</param>
    /// <param name="value">属性值</param>
    private void SetPropertyValue(object objectValue, string propertyName, object? value)
    {
        if (value == null) return;
        var propertyInfo = objectValue.GetType().GetProperty(propertyName);
        if (typeof(IList).IsAssignableFrom(propertyInfo.PropertyType))
        {
            var newList = Activator.CreateInstance(typeof(List<>).MakeGenericType(propertyInfo.PropertyType.GenericTypeArguments));
            propertyInfo.SetValue(objectValue, newList, null);
            var addMethod = newList.GetType().GetMethod("Add");
            foreach (var item in (IEnumerable)value)
            {
                addMethod.Invoke(newList, new object[] { item });
            }
        }
        else
        {
            propertyInfo.SetValue(objectValue, value, null);
        }
    }
}
